use crate::{
    reply::{Code, Reply},
    state::State,
};
use entity::{personnel, prelude::Personnel, resignation};
use poem::{
    handler,
    web::{Data, Json, Path},
};
use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, IntoActiveModel};

#[handler]
pub async fn batch(Data(State { db, .. }): Data<&State>) -> Reply<Vec<personnel::Model>> {
    let personnels = Personnel::find().all(db).await.unwrap();

    Reply::new().data(personnels)
}

#[handler]
pub async fn get(
    Data(State { db, .. }): Data<&State>,
    Path(id): Path<i64>,
) -> Reply<personnel::Model> {
    let personnel = Personnel::find_by_id(id).one(db).await.unwrap();

    personnel.map_or_else(
        || Reply::new().code(Code::NoItem).msg(id.to_string()),
        |p| Reply::new().data(p),
    )
}

#[handler]
pub async fn create(
    Data(State { db, id_bucket, .. }): Data<&State>,
    Json(personnel): Json<personnel::InsertModel>,
) -> Reply {
    let id = id_bucket.lock().await.get_id();
    let name = personnel.name.clone();
    let mut reply = Reply::new();
    let mut personnel = personnel.into_active_model();

    personnel.id = ActiveValue::Set(id);

    if personnel.insert(db).await.is_err() {
        reply.set_code(Code::DuplicateItem).set_msg(name);
    }

    reply
}

#[handler]
pub async fn update(
    Data(State { db, .. }): Data<&State>,
    Json(personnel): Json<personnel::UpdateModel>,
) -> Reply {
    let personnel = personnel.into_active_model();
    let _ = personnel.update(db).await;

    Reply::new()
}

#[handler]
pub async fn delete(
    Data(State { db, .. }): Data<&State>,
    Path(id): Path<i64>,
    Json(resignation): Json<resignation::UpsertModel>,
) -> Reply {
    let personnel = Personnel::find_by_id(id).one(db).await.unwrap();

    match personnel {
        None => Reply::new().code(Code::NoItem).msg(id.to_string()),

        Some(personnel) => {
            let resignation_id = personnel.resignation_id;
            let mut personnel = personnel.into_active_model();

            personnel.is_talent = ActiveValue::Set(resignation.be_talent);
            personnel.is_employed = ActiveValue::Set(false);

            let mut resignation = resignation.into_active_model();

            match resignation_id {
                // 离职过
                Some(rid) => {
                    resignation.id = ActiveValue::Unchanged(rid);
                    let _ = resignation.update(db).await;
                }

                // 未曾离职
                None => {
                    let rid = resignation.insert(db).await.unwrap().id;

                    personnel.resignation_id = ActiveValue::Set(Some(rid));
                }
            }

            let _ = personnel.update(db).await;
            Reply::new()
        }
    }
}
